package AES

import (
	"bytes"
	"crypto/aes"
	"errors"
)

type ecb struct {
}

// PKCS7Padding 填充
func (e *ecb) PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding 去除填充
func (e *ecb) PKCS7UnPadding(origData []byte) ([]byte, error) {
	length := len(origData)
	if length == 0 {
		return nil, errors.New("invalid data")
	}
	unpadding := int(origData[length-1])
	if unpadding > length {
		return nil, errors.New("invalid padding")
	}
	return origData[:(length - unpadding)], nil
}

// Encrypt AES ECB模式加密
func (e *ecb) Encrypt(plaintext, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// PKCS7填充
	plaintext = e.PKCS7Padding(plaintext, block.BlockSize())

	ciphertext := make([]byte, len(plaintext))
	blockSize := block.BlockSize()

	for bs, be := 0, blockSize; bs < len(plaintext); bs, be = bs+blockSize, be+blockSize {
		block.Encrypt(ciphertext[bs:be], plaintext[bs:be])
	}

	return ciphertext, nil
}

// Decrypt AES ECB模式解密
func (e *ecb) Decrypt(ciphertext, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	if len(ciphertext)%block.BlockSize() != 0 {
		return nil, errors.New("ciphertext is not a multiple of the block size")
	}

	plaintext := make([]byte, len(ciphertext))
	blockSize := block.BlockSize()

	for bs, be := 0, blockSize; bs < len(ciphertext); bs, be = bs+blockSize, be+blockSize {
		block.Decrypt(plaintext[bs:be], ciphertext[bs:be])
	}

	// 去除PKCS7填充
	plaintext, err = e.PKCS7UnPadding(plaintext)
	if err != nil {
		return nil, err
	}

	return plaintext, nil
}
